package poker.plans.croupier;

import java.util.*;

import poker.beliefs.*;
import jadex.runtime.*;
import jadex.adapter.fipa.*;


public class GetBetPlan extends Plan {
	
	private Table t;
	private List<AgentIdentifier> gamers;
	private AgentIdentifier[] players;
	private IMessageEvent msg;
	private int maxbet;
	private Bet bet;
	private List<AgentIdentifier> olds;
	private IMessageEvent answer;
	private int totalpot;
	private Hashtable<AgentIdentifier,Integer> pot;
	
	public void body() {
		System.out.println("CROUPIER : Receiving bets");
		//Get tables, gamers, pot and players
		t = (Table) getBeliefbase().getBelief("table").getFact();
		gamers = (List) getBeliefbase().getBelief("gamers").getFact();
		//Total pot accumulated
		totalpot = ((Integer)getBeliefbase().getBelief("acpot").getFact()).intValue();
		players = t.getPlayers();
		//Money played by each player
		pot = new Hashtable<AgentIdentifier,Integer>();
		olds = new ArrayList();
		
		//In the PREFLOP round things go little bit different
		if (t.getNumRound() == Table.PREFLOP) {
			preflopbettinground();
		}
		else {
			bettinground();
		}

		//Update gamers, the pot
		getBeliefbase().getBelief("gamers").setFact(gamers);
		getBeliefbase().getBelief("acpot").setFact(new Integer(totalpot));
		System.out.println("CROUPIER: Betting finished!");
	}
	
	private void preflopbettinground() {
		//	We set the maxbet as 0
		maxbet = 0;
		msg = createMessageEvent("bet_start");
		msg.getParameterSet(SFipa.RECEIVERS).addValue(players[1]);
		msg.setContent(new Integer(maxbet));
		answer = sendMessageAndWait(msg,1000);
		System.out.println("CROUPIER: Bet received");
		bet = ((DoBet) answer.getContent()).getBet();
		maxbet = bet.getMoney();
		pot.put(players[1], new Integer(maxbet));
		if (bet.getResponse() != Bet.FOLD ) { gamers.add(players[1]); }
		
		//Ask the rest of the players what they're going to do
		for (int i = 2; i < players.length; i++) {
			msg = createMessageEvent("bet_start");
			msg.getParameterSet(SFipa.RECEIVERS).addValue(players[i]);
			msg.setContent(new Integer(maxbet));
			answer = sendMessageAndWait(msg,1000);
			System.out.println("CROUPIER: Bet received");
			bet = ((DoBet) answer.getContent()).getBet();
			switch (bet.getResponse()) {
			case Bet.CALL:
				gamers.add(players[i]);
				pot.put(players[i], new Integer(maxbet));
				break;
			case Bet.RAISE: //Check if raise money > maxbet
				olds.addAll(gamers);
				gamers.clear();
				gamers.add(players[i]);
				maxbet = bet.getMoney();
				pot.put(players[i], new Integer(maxbet));
				break;
			default:
				//If he folds we have nothing to do.
				//If he checks there's an error since he has to call or raise the big blind
				//If he Blinds there's an error but since we're programming the players too that's no problem :p
			}
		}
		//Now we ask the small blind
		msg = createMessageEvent("bet_start");
		msg.getParameterSet(SFipa.RECEIVERS).addValue(players[0]);
		msg.setContent(new Integer(maxbet));
		answer = sendMessageAndWait(msg,1000);
		System.out.println("CROUPIER: Bet received");
		bet = ((DoBet) answer.getContent()).getBet();
		switch (bet.getResponse()) {
		case Bet.CALL:
			gamers.add(players[0]);
			pot.put(players[0], new Integer(maxbet));
			break;
		case Bet.RAISE: //Check if raise money > maxbet
			olds.addAll(gamers);
			gamers.clear();
			gamers.add(players[0]);
			maxbet = bet.getMoney();
			pot.put(players[0], new Integer(maxbet));
			break;
		default:
			//If he folds we have nothing to do.
			//If he checks there's an error since he has to call or raise the big blind
			//If he Blinds there's an error but since we're programming the players too that's no problem :p
		}
		//And now we should ask the old guys what do they want to do
		//To simplify this we suppose that they can only call or fold
		Iterator it = olds.iterator();
		AgentIdentifier id;
		while(it.hasNext()) {
			id = (AgentIdentifier) it.next();
			msg = createMessageEvent("bet_start");
			msg.getParameterSet(SFipa.RECEIVERS).addValue(id);
			msg.setContent(new Integer(maxbet));
			answer = sendMessageAndWait(msg,1000);
			System.out.println("CROUPIER: Bet received");
			bet = ((DoBet) answer.getContent()).getBet();
			switch (bet.getResponse()) {
			case Bet.CALL:
				gamers.add(id);
				pot.put(id, new Integer(maxbet));
				break;
			default:
			}
		}
		
		//Calculate totalpot
		Integer euro;
		for (int i = 0; i< players.length; i++) {
			euro = pot.get(players[i]);
			if (euro != null) {
				totalpot += euro.intValue();
			}
		}
	}
	
	private void bettinground() {
		//Set the maxbet to 0
		//In each round maxbet starts as 0
		//Players know what was the maxbet of the past round with their belief currentbet
		//So when they say raise 200 they have bet in total currentbet+200 though in the answer to bet_start it says raise 200
		int maxbet = 0;
		//Ask the gamers what they're going to do
		//We create a copy of the list because we need to clear gamers
		List<AgentIdentifier> aux = new ArrayList(gamers);
		gamers.clear();
		Iterator it = aux.iterator();
		
		//Someone has raised??
		int raised = 0;
		
		AgentIdentifier id;
		while(it.hasNext()) {
			id = (AgentIdentifier) it.next();
			msg = createMessageEvent("bet_start");
			msg.getParameterSet(SFipa.RECEIVERS).addValue(id);
			msg.setContent(new Integer(maxbet));
			answer = sendMessageAndWait(msg,1000);
			System.out.println("CROUPIER: Bet received");
			bet = ((DoBet) answer.getContent()).getBet();
			switch (bet.getResponse()) {
			case Bet.RAISE: //Check if raise money > maxbet
				olds.addAll(gamers);
				gamers.clear();
				gamers.add(id);
				maxbet = bet.getMoney();
				pot.put(id, new Integer(maxbet));
				raised++;
				break;
			case Bet.CALL: //This cannot be done until somebody has raised
				gamers.add(id);
				pot.put(id, new Integer(maxbet));
				break;
			case Bet.CHECK: //This cannot be done if somebody has raised
				gamers.add(id);
				pot.put(id, new Integer(maxbet));
				break;
			default:
				//If he folds we have nothing to do
				//If he Blinds there's an error but since we're programming the players too that's no problem :p
			}
		}
		//And now we ask the olds
		it = olds.iterator();
		while (it.hasNext()){
			id = (AgentIdentifier) it.next();
			msg = createMessageEvent("bet_start");
			msg.getParameterSet(SFipa.RECEIVERS).addValue(id);
			msg.setContent(new Integer(maxbet));
			answer = sendMessageAndWait(msg,1000);
			System.out.println("CROUPIER: Bet received");
			bet = ((DoBet) answer.getContent()).getBet();
			switch (bet.getResponse()) {
			case Bet.CALL:
				gamers.add(id);
				pot.put(id, new Integer(maxbet));
				break;
			default:
			}
		}
		
		//Calculate totalpot
		Integer euro;
		for (int i = 0; i< players.length; i++) {
			euro = pot.get(players[i]);
			if (euro != null) {
				totalpot += euro.intValue();
			}
		}
	}
}
